package cn.stylefeng.guns.modular.gridsystem.timer;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.guns.core.timer.TimerTaskRunner;
import cn.stylefeng.guns.modular.gridsystem.entity.BizDevice;
import cn.stylefeng.guns.modular.gridsystem.entity.BizHealthTrends;
import cn.stylefeng.guns.modular.gridsystem.entity.BizUploadScore;
import cn.stylefeng.guns.modular.gridsystem.mapper.BizDeviceMapper;
import cn.stylefeng.guns.modular.gridsystem.mapper.BizUploadScoreMapper;
import cn.stylefeng.guns.modular.gridsystem.service.BizHealthTrendsService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 设备健康趋势计算
 *
 * @author rdp
 * @date 2022/12/30 10:49
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class DeviceHealthTrendsTaskRunner implements TimerTaskRunner {

    private final BizHealthTrendsService bizHealthTrendsService;

    private final BizUploadScoreMapper uploadScoreMapper;

    private final BizDeviceMapper deviceMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void action() {
//        log.info(">>> 更新设备健康趋势的定时任务开始执行... ");

        // 获取前一天的时间
        String lastDay = DateUtil.format(DateUtil.offsetDay(DateTime.now(), -1), "yyyy-MM-dd");
        String[] hourArr = new String[]{"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"};

        List<BizUploadScore> scoreList = uploadScoreMapper.selectList(new LambdaQueryWrapper<BizUploadScore>().likeRight(BizUploadScore::getCreatedAt, lastDay));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 获取所有的设备主键
        List<Integer> deviceIds = deviceMapper.selectList(null).stream().map(BizDevice::getId).collect(Collectors.toList());

        List<BizHealthTrends> healthTrendsList = new ArrayList<>();

        if (ObjectUtil.isNotEmpty(deviceIds)) {

            for (Integer deviceId : deviceIds) {

                List<BizUploadScore> deviceScores = scoreList.stream().filter(item -> deviceId.equals(item.getDeviceId())).collect(Collectors.toList());

                // 如果查询到有数据，则写入设备健康数据
                if (ObjectUtil.isNotEmpty(deviceScores)) {

                    // 从0点开始到23点结束，将一天的时间拆成24个小时
                    for (String hour : hourArr) {

                        String dataStr = lastDay + " " + hour;
                        List<BizUploadScore> scores = deviceScores.stream()
                                .filter(item -> sdf.format(item.getCreatedAt()).startsWith(dataStr))
                                .collect(Collectors.toList());

                        if (ObjectUtil.isEmpty(scores)) {

                            // 没有数据
                            BizHealthTrends healthTrends = BizHealthTrends.builder()
                                    .deviceId(deviceId)
                                    .avgScore(0f)
                                    .statisticalTime(DateUtil.parse(dataStr + ":00:00"))
                                    .build();
                            healthTrendsList.add(healthTrends);

                        } else {

                            // 有数据则进行计算
                            float totalScore = 0f;
                            for (BizUploadScore score : scores) {
                                totalScore += ObjectUtil.isEmpty(score.getScore()) ? 0 : Float.parseFloat(score.getScore());
                            }

                            BizHealthTrends healthTrends = BizHealthTrends.builder()
                                    .deviceId(deviceId)
                                    // 平均分数保留两位小数位
                                    .avgScore(Float.parseFloat(String.format("%.2f", totalScore / scores.size())))
                                    .statisticalTime(DateUtil.parse(dataStr + ":00:00"))
                                    .build();
                            healthTrendsList.add(healthTrends);

                        }
                    }

                }

            }

            // 批量保存数据
            if (ObjectUtil.isNotEmpty(healthTrendsList)) {
                bizHealthTrendsService.saveBatch(healthTrendsList, 500);
            }

//            log.info(">>> 更新设备健康趋势的定时任务执行结束... ");

        }

    }
}
